/**
 * Copyright (c) 2011-2014, liuchangng@qq.com.
 *
 * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License at
 *
 * <p>http://www.apache.org/licenses/LICENSE-2.0
 *
 * <p>Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.autumnorange.commons.util;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;

/**
 * 反射工具类.
 *
 * @author hubin @Date 2016-04-16
 */
public class ReflectUtil {

  /** 根据对象，返回一个class对象，用于获取方法 */
  public static Class<?> getClass(Object obj) {
    try {
      return Class.forName(obj.getClass().getName());
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 根据对象，获取某个方法
   *
   * @param obj 对象
   * @param methodName 方法名
   * @param parameterTypes 该方法需传的参数类型，如果不需传参，则不传
   */
  public static Method getMethod(Object obj, String methodName, Class<?>... parameterTypes) {
    try {
      Method method = getClass(obj).getDeclaredMethod(methodName, parameterTypes);
      method.setAccessible(true);
      return method;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  public static Method getMethod(Class<?> cls, String methodName, Class<?>... parameterTypes) {
    try {
      Method method = cls.getDeclaredMethod(methodName, parameterTypes);
      method.setAccessible(true);
      return method;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 直接传入对象、方法名、参数，即可使用该对象的隐藏方法
   *
   * @param obj
   * @param methodName
   * @param parameter
   */
  public static Object invoke(Object obj, String methodName, Object... parameter) {
    Class<?>[] parameterTypes = new Class<?>[parameter.length];
    for (int i = 0; i < parameterTypes.length; i++) {
      parameterTypes[i] = parameter[i].getClass();
    }
    try {
      return getMethod(obj, methodName, parameterTypes).invoke(obj, parameter);
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 直接传入类名、方法名、参数，即可使用该对象的隐藏静态方法
   *
   * @param cls
   * @param methodName
   * @param parameter
   */
  public static Object invoke(Class<?> cls, String methodName, Object... parameter) {
    Class<?>[] parameterTypes = new Class<?>[parameter.length];
    for (int i = 0; i < parameterTypes.length; i++) {
      parameterTypes[i] = parameter[i].getClass();
    }
    try {
      return getMethod(cls, methodName, parameterTypes).invoke(null, parameter);
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 判断一个类是否为基本类型包装类,基本数据类型。
   *
   * @param clazz 要判断的类。
   * @return true 表示为基本数据类型。
   */
  public static boolean isBaseDataType(Class clazz) {
    return (clazz.equals(String.class)
        || clazz.equals(Integer.class)
        || clazz.equals(Byte.class)
        || clazz.equals(Long.class)
        || clazz.equals(Double.class)
        || clazz.equals(Float.class)
        || clazz.equals(Character.class)
        || clazz.equals(Short.class)
        || clazz.equals(BigDecimal.class)
        || clazz.equals(BigInteger.class)
        || clazz.equals(Boolean.class)
        || clazz.equals(Date.class)
        || clazz.isPrimitive());
  }

  public static boolean isBaseDataType(String colum) {
    return (colum.contains("String")
        || colum.contains("Integer")
        || colum.contains("Byte")
        || colum.contains("Long")
        || colum.contains("Double")
        || colum.contains("Float")
        || colum.contains("Character")
        || colum.contains("Short")
        || colum.contains("BigDecimal")
        || colum.contains("BigInteger")
        || colum.contains("Boolean")
        || colum.contains("Date")
        || colum.contains("char")
        || colum.contains("byte")
        || colum.contains("short")
        || colum.contains("int")
        || colum.contains("long")
        || colum.contains("float")
        || colum.contains("double")
        || colum.contains("boolean")
        || colum.contains("date"));
  }
}
